#include "Core.h"


__BEGIN_NAMESPACE


DWORD WINAPI g_ThreadProc( __in  LPVOID lpParameter )
{
	Thread* pthread = static_cast<Thread*>(lpParameter);
	Runnable* prun = pthread->GetRunnable();
	void* pparam = pthread->GetParam();
	int* pret = pthread->GetReturn();
	int ret = prun->Run(pparam);
	if( pret ) {
		*pret = ret;
	}
	return 0;
}

Thread::Thread():m_headle(0), m_state(EThreadState_Init), m_run(0), m_param(0), m_ret(0)
{
}

Thread::~Thread()
{
	if( EThreadState_Init!=GetState() ) {
		Cancel();
	}
}

int Thread::Start(Runnable* fun, void* param/*=0*/, int* ret/*=0*/)
{
	Assert(m_headle==0);
	m_run = fun;
	m_param = param;
	m_ret = ret;
	DWORD id;
	m_headle = ::CreateThread(NULL, 0, g_ThreadProc, this, NULL, &id );
	if( m_headle ) {
		m_state = EThreadState_Running;
	}
	return 0!=m_headle;
}

bool Thread::Join( const unsigned int timeout/*=0*/ )
{
	if(0==m_headle)
		return false;

	bool ret = WAIT_OBJECT_0==::WaitForSingleObject( m_headle, timeout);
	m_state = EThreadState_Init;
	return ret;
}

bool Thread::Cancel()
{
	Assert(m_headle!=0);
	if( m_state!=EThreadState_Running && m_state!=EThreadState_Suspend )
		return false;
	bool ret = 0!=::TerminateThread(m_headle, -1);
	if( ret ) {
		::CloseHandle(m_headle);
		m_headle = 0;
		m_state = EThreadState_Init;
	}
	return ret;
}

bool Thread::Suspend()
{
	Assert(m_headle!=0);
	if( m_state!=EThreadState_Running )
		return false;	
	return (DWORD)-1!=::SuspendThread(m_headle);
}

bool Thread::Resume()
{
	Assert(m_headle!=0);
	if( m_state!=EThreadState_Suspend )
		return false;
	return (DWORD)-1!=::ResumeThread(m_headle);
}


__END_NAMESPACE
